package NewTmas.Graphs;

/**
 * Created by IntelliJ IDEA.
 * User: abhatnag
 * Date: 7/14/11
 * Time: 9:08 AM
 * To change this template use File | Settings | File Templates.
 */


import NewTmas.FramesandPanels.JobGraphPanel;
import NewTmas.Popupmenus.GraphVizGrappaAdapter;
import att.grappa.*;
import taskmaster.job.Dependency;
import taskmaster.job.JobAllTasksCollection;
import taskmaster.job.TaskStatus;
import taskmaster.util.Global;

import javax.swing.*;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;

public class GraphVizGraph
{


    List<Dependency> dependencies;
    public HashMap<String, TaskStatus> task_status;
    HashMap<String, Character> taskType;
    public HashMap<String, String> display_name;
    JobGraphPanel jobGraphPanel;
    Graph graph = null;

    public GrappaPanel gp;
    String jobName;
    public String graphStr = new String();
    public JScrollPane jsp;
    int width, height;
    /*
   * Constructor to create job graphs in ops mode
   * */

    public GraphVizGraph(List<Dependency> dependencies, HashMap<String, TaskStatus> task_status, LinkedHashMap<String, Character> taskType, HashMap<String, String> display_name, JobGraphPanel jobGraphPanel, int width, int height)
    {
        this.dependencies = dependencies;
        this.task_status = task_status;
        this.taskType = taskType;
        this.display_name = display_name;
        this.width = width;
        this.height = height;
        this.jobGraphPanel = jobGraphPanel;
        this.jobName = jobGraphPanel.job;
        this.graph = new Graph(jobName, true, false);
        Init();


    }


    /*
    * Constructor to create job graphs in edit mode
    * */

    public GraphVizGraph(JobAllTasksCollection alltc, String job, int graphWidth, int graphHeight)
    {
        this.dependencies = alltc.dependency_task;
        this.width = graphWidth;
        this.height = graphHeight;
        this.taskType = alltc.task_type;
        this.display_name = alltc.defaultNames;
        this.jobName = job;
        this.graph = new Graph(jobName, true, false);
        Init();
    }

    public void Init()
    {

        createGraph();

        jsp = new JScrollPane();
        jsp.getViewport().setBackingStoreEnabled(true);

        gp = new GrappaPanel(graph);
        if (task_status != null)
        {
            gp.addGrappaListener(new GraphVizGrappaAdapter(jobGraphPanel));
        }
        gp.setScaleToFit(false);


        jsp.setViewportView(gp);


/* to save  the dot file

File f=new File(temp+File.separator+jobName+".dot");
//        for(int i=0;i<graphStr.size();i++){
//
//            System.out.print(graphStr.get(i));
//
//        }

      BufferedWriter out = null;
      try {
          out = new BufferedWriter(new FileWriter(f));

          for(int i=0;i<graphStr.size();i++){

             out.write(graphStr.get(i));
              out.write("\n");
          }
          out.close();
      } catch (IOException e1) {
          JOptionPane.showMessageDialog(null,"Error retrieving/saving the Help File"+e1.getMessage(),"Error",JOptionPane.ERROR_MESSAGE);
          e1.printStackTrace();
      }
*/
    }

    /*  Specifying the graph attributes while creating the dot for the graph
   PAGE Attribute:  This refers to the graph dimensions on  'PRINTED' output of the graph.But it works only for postscript
    output.
   RATIO attribute:Aspect ratio for the graph.Fill ensures the graph nodes to uniformly shrink/expand to comply to SIZE
   attribute.
   SIZE attribute :Width and height of the graph drawing.
   * Refer http://www.graphviz.org/doc/info/attrs.html#d:lwidth   for complete documentation by GraphViz.
   * */
    private void createGraph()
    {


        graph.setAttribute("page", "8.5,11"); //page as default as in old Perl lib .
        graph.setAttribute("ratio", "fill");
        graph.setAttribute("size", String.valueOf(width + "," + height));//default as in old Perl lib

        HashMap<String, Node> nodeSet = new HashMap<String, Node>();
        TreeMap<String, Character> sortedTaskNames = new TreeMap<String, Character>();
        sortedTaskNames.putAll(taskType);
        for (Map.Entry<String, Character> entry : sortedTaskNames.entrySet())
        {

            Node n = new Node(graph, entry.getKey());
            n.setAttribute("label", display_name.get(entry.getKey()));
            n.setAttribute("pencolor", "black");
            if (task_status != null && task_status.containsKey(entry.getKey()))
            {
                n.setAttribute("color", task_status.get(entry.getKey()).getColor());
            } else
            {
                n.setAttribute("color", "skyblue1");
            }


            n.setAttribute("shape", Global.task_shape2.get(taskType.get(entry.getKey())));
            n.setAttribute("style", "filled");
            nodeSet.put(entry.getKey(), n);

        }

        for (Dependency d : dependencies)
        {

            Edge e = new Edge(graph, nodeSet.get(d.getDependency()), nodeSet.get(d.getTask()));
            e.setAttribute("label", d.description);
            e.setAttribute("fontsize", 9.5);

        }

        graph.setEditable(true);
        graph.setSelectable(true);
        graph.setErrorWriter(new PrintWriter(System.err, true));


        StringWriter writer = new StringWriter();
        graph.printGraph(writer);
        String tms_dot = System.getProperty("TMS_DOT");
        String[] dotArgs = {tms_dot};

        try
        {
            Process dotProcess = Runtime.getRuntime().exec(dotArgs, null, null);
            GrappaSupport.filterGraph(graph, dotProcess);

            dotProcess.getOutputStream().close();

        }
        catch (Exception exc)
        {
            throw new Error(exc);
        }
        graphStr = (writer.toString());


        System.out.println(graphStr);         //to print dot


    }


    /*in order to refresh the graph we do not write the dot file again.Instead,we just recreate the task_status and recolor the graph accordingly */
    public void refreshGraphViz()
    {

        for (Map.Entry<String, String> e : display_name.entrySet())
        {
            Node node = graph.findNodeByName(e.getKey());
            if (node != null)
            {
                if (task_status != null && task_status.containsKey(e.getKey()))
                {
                    node.setAttribute("color", task_status.get(e.getKey()).getColor());
                } else
                {
                    node.setAttribute("color", "skyblue1");
                }
                node.setAttribute("style", "filled");
            } else
            {
                System.err.println("Unable to find node for name:" + e.getKey());
            }
        }
        graph.repaint();
    }


    public Graph getGraph()
    {

        return graph;

    }


    /*to redraw the entire graph in edit mode.Essentially we use the same graph object,clear all nodes
    and then redraw it the old way and call repaint */
    public void redrawGraph(List<Dependency> newdependencies, LinkedHashMap<String, Character> newtaskType, HashMap<String, String> newdisplay_name)
    {
        for (Node n : graph.nodeElementsAsArray())
        {
            n.delete();
        }

        taskType = newtaskType;
        dependencies = newdependencies;
        display_name = newdisplay_name;

        createGraph();

        graph.repaint();
    }

    public GrappaPanel getGrappaPanel()
    {

        return gp;
    }

}

